package com.ruoyi.project.fusion.algorithms;

import com.ruoyi.project.fusion.domain.MaterialManagementAggInfo;
import com.ruoyi.project.fusion.domain.MaterialManagementScores;
import com.ruoyi.project.fusion.utils.ComputeUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MaterialManagementAlgorithm {
    public List<MaterialManagementScores> compute(List<MaterialManagementAggInfo> materialManagementAggInfos) {
        List<MaterialManagementScores> scoresList = new ArrayList<>();

        // 按照 chainType、scenario、product 分组
        Map<List<String>, List<MaterialManagementAggInfo>> groupedInfos = materialManagementAggInfos.stream()
                .collect(Collectors.groupingBy(info -> Arrays.asList(
                        info.getChainType(),
                        info.getScenario(),
                        info.getProduct(),
                        info.getEvent()
                )));

        for (Map.Entry<List<String>, List<MaterialManagementAggInfo>> entry : groupedInfos.entrySet()) {
            List<MaterialManagementAggInfo> group = entry.getValue();

            // 归一化数据
            List<Double> normalizedInventoryVolume = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getTotalInventoryVolume).collect(Collectors.toList()));
            List<Double> normalizedWarehouseQuantity = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgWarehouseQuantity).collect(Collectors.toList()));
            List<Double> normalizedWarehouseAutomationLevel = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgWarehouseAutomationLevel).collect(Collectors.toList()));
            List<Double> normalizedDeliveryCycle = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgDeliveryCycle).collect(Collectors.toList()));
            List<Double> normalizedTransportationCapacity = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgTransportationCapacity).collect(Collectors.toList()));
            List<Double> normalizedOnTimeDeliveryRate = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgOnTimeDeliveryRate).collect(Collectors.toList()));
            List<Double> normalizedTransportationCost = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgTransportationCost).collect(Collectors.toList()));
            List<Double> normalizedTransportationDamageRate = ComputeUtils.normalizeValues(group.stream().map(MaterialManagementAggInfo::getAvgTransportationDamageRate).collect(Collectors.toList()));

            // 计算各项指标的标准差
            double stdDevInventoryVolume = ComputeUtils.calculateStandardDeviation(normalizedInventoryVolume);
            double stdDevWarehouseQuantity = ComputeUtils.calculateStandardDeviation(normalizedWarehouseQuantity);
            double stdDevWarehouseAutomationLevel = ComputeUtils.calculateStandardDeviation(normalizedWarehouseAutomationLevel);
            double stdDevDeliveryCycle = ComputeUtils.calculateStandardDeviation(normalizedDeliveryCycle);
            double stdDevTransportationCapacity = ComputeUtils.calculateStandardDeviation(normalizedTransportationCapacity);
            double stdDevOnTimeDeliveryRate = ComputeUtils.calculateStandardDeviation(normalizedOnTimeDeliveryRate);
            double stdDevTransportationCost = ComputeUtils.calculateStandardDeviation(normalizedTransportationCost);
            double stdDevTransportationDamageRate = ComputeUtils.calculateStandardDeviation(normalizedTransportationDamageRate);

            // 计算总标准差
            double totalStdDev = stdDevInventoryVolume + stdDevWarehouseQuantity + stdDevWarehouseAutomationLevel + stdDevDeliveryCycle +
                    stdDevTransportationCapacity + stdDevOnTimeDeliveryRate + stdDevTransportationCost + stdDevTransportationDamageRate;

            // 计算权重
            double weightInventoryVolume = (totalStdDev == 0) ? 0.125 : stdDevInventoryVolume / totalStdDev;
            double weightWarehouseQuantity = (totalStdDev == 0) ? 0.125 : stdDevWarehouseQuantity / totalStdDev;
            double weightWarehouseAutomationLevel = (totalStdDev == 0) ? 0.125 : stdDevWarehouseAutomationLevel / totalStdDev;
            double weightDeliveryCycle = (totalStdDev == 0) ? 0.125 : stdDevDeliveryCycle / totalStdDev;
            double weightTransportationCapacity = (totalStdDev == 0) ? 0.125 : stdDevTransportationCapacity / totalStdDev;
            double weightOnTimeDeliveryRate = (totalStdDev == 0) ? 0.125 : stdDevOnTimeDeliveryRate / totalStdDev;
            double weightTransportationCost = (totalStdDev == 0) ? 0.125 : stdDevTransportationCost / totalStdDev;
            double weightTransportationDamageRate = (totalStdDev == 0) ? 0.125 : stdDevTransportationDamageRate / totalStdDev;

            // 计算分数
            for (int i = 0; i < group.size(); i++) {
                MaterialManagementAggInfo info = group.get(i);

                double score = (normalizedInventoryVolume.get(i) * weightInventoryVolume) +
                        (normalizedWarehouseQuantity.get(i) * weightWarehouseQuantity) +
                        (normalizedWarehouseAutomationLevel.get(i) * weightWarehouseAutomationLevel) +
                        (normalizedDeliveryCycle.get(i) * weightDeliveryCycle) +
                        (normalizedTransportationCapacity.get(i) * weightTransportationCapacity) +
                        (normalizedOnTimeDeliveryRate.get(i) * weightOnTimeDeliveryRate) +
                        (normalizedTransportationCost.get(i) * weightTransportationCost) +
                        (normalizedTransportationDamageRate.get(i) * weightTransportationDamageRate);

                MaterialManagementScores materialManagementScore = new MaterialManagementScores();
                materialManagementScore.setChainType(info.getChainType());
                materialManagementScore.setEnterpriseName(info.getEnterpriseName());
                materialManagementScore.setScenario(info.getScenario());
                materialManagementScore.setProduct(info.getProduct());
                materialManagementScore.setEvent(info.getEvent());
                materialManagementScore.setScore(ComputeUtils.roundToTwoDecimalPlaces((float) score));

                scoresList.add(materialManagementScore);
            }
        }

        return scoresList;
    }
}
